/**
 * This file is part of aion-emu <aion-emu.com>.
 *
 *  aion-emu is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  aion-emu is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with aion-emu.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionemu.gameserver.network.aion.clientpackets;

import com.aionemu.gameserver.controllers.movement.MovementMask;
import com.aionemu.gameserver.model.gameobjects.moveData.PlayableMoveData;
import com.aionemu.gameserver.model.gameobjects.player.Player;
import com.aionemu.gameserver.network.aion.AbstractAionClientPacket;
import com.aionemu.gameserver.taskmanager.tasks.GroupAllianceUpdater;

/**
 * Packet about player movement.
 * 
 * @author Lyahim, -Nemesiss-
 * 
 */
public class CM_MOVE extends AbstractAionClientPacket
{

	private byte				type;
	private byte				heading;
	private float				x = 0f, y = 0f, z = 0f, x2 = 0f, y2 = 0f, z2 = 0f, vehicleX = 0f, vehicleY = 0f, vehicleZ = 0f, vectorX = 0f, vectorY = 0f, vectorZ = 0f;
	private byte				glideFlag;
	private int 				unk1, unk2;
	/**
	 * Constructs new instance of <tt>CM_MOVE </tt> packet
	 * 
	 * @param opcode
	 */
	public CM_MOVE(int opcode)
	{
		super(opcode);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void readImpl()
	{
		Player player = getClient().getActivePlayer();

		if (!player.isSpawned())
			return;

		x = readF();
		y = readF();
		z = readF();

		heading = (byte) readC();
		type = (byte) readC();

		if ((type & MovementMask.STARTMOVE) == MovementMask.STARTMOVE)
		{
			if ((type & MovementMask.MOUSE) == 0)
			{
				vectorX = readF();
				vectorY = readF();
				vectorZ = readF();
				x2 = vectorX+x;
				y2 = vectorY+y;
				z2 = vectorZ+z;
			}
			else
			{
				x2 = readF();
				y2 = readF();
				z2 = readF();
			}
		}
		if ((type & MovementMask.GLIDE) == MovementMask.GLIDE)
		{
			glideFlag = (byte) readC();
		}
		if ((type & MovementMask.VEHICLE) == MovementMask.VEHICLE)
		{
			unk1 = readD();
			unk2 = readD();
			vehicleX = readF();
			vehicleY = readF();
			vehicleZ = readF();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void runImpl()
	{
		Player player = getClient().getActivePlayer();
		PlayableMoveData m = player.getMoveData();
		m.movementMask = type;
		
		if ((type & MovementMask.GLIDE) == MovementMask.GLIDE)
		{
			m.glideFlag = glideFlag;
			player.getFlyController().switchToGliding();
		}
		else
			player.getFlyController().onStopGliding();
		
		if (type == 0)
		{
			player.onStopMove(x, y, z, heading);
			player.getFlyController().onStopGliding();
		}
		else if ((type & MovementMask.STARTMOVE) == MovementMask.STARTMOVE)
		{
			if ((type & MovementMask.MOUSE) == 0)
			{
				m.vectorX = vectorX;
				m.vectorY = vectorY;
				m.vectorZ = vectorZ;
			}
			player.onMoveTo(x, y, z, x2, y2, z2, heading, type);
		}
		else
			player.onMove(x, y, z, heading, type);

		if ((type & MovementMask.VEHICLE) == MovementMask.VEHICLE)
		{
			m.unk1 = unk1;
			m.unk2 = unk2;
			m.vehicleX = vehicleX;
			m.vehicleY = vehicleY;
			m.vehicleZ = vehicleZ;
		}
		if (player.isInGroup() || player.isInAlliance())
		{
			GroupAllianceUpdater.getInstance().add(player);
		}

		//TODO Need rework fall damage.
		/**
		float distance = playerZ - z;
		if (FallDamageConfig.ACTIVE_FALL_DAMAGE && player.isInState(CreatureState.ACTIVE) && !player.isInState(CreatureState.FLYING)
				&& !player.isInState(CreatureState.GLIDING) && (type == 0 || distance >= FallDamageConfig.MAXIMUM_DISTANCE_MIDAIR))
		{
			if (StatFunctions.calculateFallDamage(player, distance))
			{
				return; // the player resurrected at his bind location.
			}
		}
*/
		if (type != 0 && player.isProtectionActive())
		{
			player.stopProtectionActiveTask();
		}
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString()
	{
		return "CM_MOVE [type=" + type + ", heading=" + heading + ", x=" + x + ", y=" + y + ", z=" + z + ", x2=" + x2 + ", y2=" + y2 + ", z2=" + z2
				+ ", vehicleX=" + vehicleX + ", vehicleY=" + vehicleY + ", vehicleZ=" + vehicleZ + ", vectorX=" + vectorX + ", vectorY=" + vectorY
				+ ", vectorZ=" + vectorZ + ", glideFlag=" + glideFlag + ", unk1=" + unk1 + ", unk2=" + unk2 + "]";
	}

}
